package meal

import (
	"context"
	"encoding/json"
	"github.com/google/uuid"
	"github.com/zeromicro/go-zero/core/logx"
	"golang.org/x/sync/errgroup"
	"insighttracking/apps/admin/auth"
	"insighttracking/apps/admin/internal/svc"
	"insighttracking/apps/admin/internal/types"
	"insighttracking/common/utils"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"
	"os"
)

type ApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *ApiLogic {
	hostname, _ := os.Hostname()
	return &ApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

func (l *ApiLogic) CreateApi(req *types.CreateMealsReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	startDate := utils.DateStrToTime(req.StartDate)
	endDate := utils.DateStrToTime(req.EndDate)
	if err != nil {
		return
	}
	mealTemplate, err := service.MealService.CreateTemplateApi(l.ctx, accountInfo.EnterpriseId, req.Name, req.Describe, startDate, endDate)
	if err != nil {
		return
	}
	templateDetails := make([]*model.MealsTemplateDetailEntity, 0)
	for _, meal := range req.Meals {
		dishesIDs, err := json.Marshal(meal.DishesIDs)
		if err != nil {
			return "", err
		}
		templateDetails = append(templateDetails, &model.MealsTemplateDetailEntity{
			MealsTemplateID: mealTemplate.ID,
			Date:            utils.DateStrToTime(meal.Date),
			Type:            meal.Type,
			Weekday:         meal.Weekday,
			DishesIds:       string(dishesIDs),
		})
	}
	err = service.MealService.BatchCreateTemplateDetailApi(l.ctx, templateDetails)
	return
}

func (l *ApiLogic) GetTemplateList(req *types.TemplateListReq) (resp types.MealsTemplateResp, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}
	meals, err := service.MealService.GetTemplateListApi(l.ctx, accountInfo.EnterpriseId, req.Name)
	list := make([]types.MealsTemplateModel, 0)
	for _, meal := range meals {
		list = append(list, types.MealsTemplateModel{
			ID:        meal.ID,
			Name:      meal.Name,
			Describe:  meal.Describe,
			StartDate: utils.TimestampToString(meal.StartDate),
			EndDate:   utils.TimestampToString(meal.EndDate),
			CreatedAt: utils.TimestampToString(meal.CreatedAt),
			UpdatedAt: utils.TimestampToString(meal.UpdatedAt),
		})
	}
	resp = types.MealsTemplateResp{
		List: list,
	}
	return
}

func (l *ApiLogic) GetTemplateDetailListApi(req *types.IdReq) (resp types.MealsTemplateDetailResp, err error) {
	template, err := service.MealService.GetByIDApi(l.ctx, req.Id)
	mealsDetail, err := service.MealService.GetTemplateDetailListApi(l.ctx, req.Id)
	if err != nil {
		return
	}
	resp.Name = template.Name
	resp.Describe = template.Describe
	resp.StartDate = utils.TimestampToString(template.StartDate)
	resp.EndDate = utils.TimestampToString(template.EndDate)
	resp.Meals = mealsDetail
	return
}

func (l *ApiLogic) EditTemplateDetailApi(req *types.MealsTemplateEditReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}
	//编辑template
	startDate := utils.DateStrToTime(req.StartDate)
	endDate := utils.DateStrToTime(req.EndDate)
	template := model.MealsTemplateEntity{
		ID:           req.TemplateID,
		Name:         req.Name,
		Describe:     req.Describe,
		StartDate:    startDate,
		EndDate:      endDate,
		EnterpriseID: accountInfo.EnterpriseId,
	}
	err = service.MealService.EditTemplateApi(l.ctx, &template)

	for _, meal := range req.Meals {
		date := utils.DateStrToTime(meal.Date)
		if date.Unix() <= endDate.Unix() && date.Unix() >= startDate.Unix() {
			dishedIDs, err := json.Marshal(meal.DishesIDs)
			if err != nil {
				return "", err
			}
			err = service.MealService.EditTemplateDetailApi(l.ctx, req.TemplateID, date, meal.Type, meal.Weekday, string(dishedIDs))
		}
	}
	return
}

func (l *ApiLogic) EditCustomerMealApi(req *types.CustomerMealsEditReq) (resp string, err error) {
	for _, meal := range req.Meals {
		date := utils.DateStrToTime(meal.Date)
		dishedIDs, err := json.Marshal(meal.DishesIDs)
		if err != nil {
			return "", err
		}
		err = service.MealService.EditCustomerMealApi(l.ctx, req.CusTomerID, date, meal.Type, meal.Weekday, string(dishedIDs))
	}
	return
}

func (l *ApiLogic) GetCustomerMealListApi(req *types.CustomerMealsListReq) (resp *types.CustomerMealsListResp, err error) {
	resp = &types.CustomerMealsListResp{}
	startDate := utils.DateStrToTime(req.StartDate)
	endDate := utils.DateStrToTime(req.EndDate)
	mealsDetail, err := service.MealService.GetCustomerMealListApi(l.ctx, req.ID, startDate, endDate)
	resp.Meals = mealsDetail
	return
}

func (l *ApiLogic) TemplateApplyApi(req *types.MealsTemplateApplyResp) (resp string, err error) {
	list, err := service.MealService.GetTemplateDetailApi(l.ctx, req.TemplateID)
	tx := dao.Use(l.svcCtx.MysqlDb).Begin()
	g, ctx := errgroup.WithContext(l.ctx)
	for _, item := range list {
		entities := make([]*model.MealsCustomerEntity, 0)
		for _, customerID := range req.CusTomerIDs {
			entity := model.MealsCustomerEntity{
				CustomerID: customerID,
				Date:       item.Date,
				Type:       item.Type,
				DishesIds:  item.DishesIds,
				Weekday:    item.Weekday,
			}
			entities = append(entities, &entity)
		}
		g.Go(func() error {
			err = service.MealService.TemplateApplyApi(ctx, tx, entities)
			return err
		})
	}
	err = g.Wait()
	if err != nil {
		if err = tx.Rollback(); err != nil {
			return
		}
	}
	if err = tx.Commit(); err != nil {
		return
	}
	return
}
